package com.katze.boot.common.exception;

import com.katze.boot.plugins.feign.ApplicationNotExistException;
import com.katze.boot.plugins.redis.exception.LimitAccessException;
import com.katze.common.Code;
import com.katze.common.Message;
import feign.FeignException;
import feign.RetryableException;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.net.ConnectException;

/**
 * @author wx
 */
@RestControllerAdvice
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler({BusinessException.class, FileNotFoundException.class, ApplicationNotExistException.class})
    @ResponseStatus(HttpStatus.OK)
    public Message handleBusinessException(Exception e) {
        log.error("系统内部业务异常，异常信息：", e);
        return Message.exception(Code.C500, e.getMessage());

    }

    @ExceptionHandler({Exception.class})
    @ResponseStatus(HttpStatus.OK)
    public Message handleException(Exception e) {
        log.error("系统内部异常，异常信息：", e);
        String message = e instanceof BusinessException ? e.getMessage():Code.C500.getDesc().concat(" :: " + e.getMessage());
        return Message.exception(Code.C500, message);

    }

    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    public Message handleHttpRequestMethodNotSupportedException(Exception e) {
        log.error("HTTP请求方式不被支持：", e);
        return Message.exception(Code.C405);
    }

    @ExceptionHandler(value = NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.OK)
    public Message handleNoHandlerFoundException(Exception e) {
        log.error("HTTP请求内容未找到：", e);
        return Message.exception(Code.C404);
    }

    @ExceptionHandler(value = LimitAccessException.class)
    @ResponseStatus(HttpStatus.OK)
    public Message handleLimitAccessException(LimitAccessException e) {
        log.error(e.getMessage());
        return Message.exception(Code.C429, e.getMessage());
    }
    @ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    public Message handleHttpMediaTypeNotSupportedException(Exception e) {
        log.error(e.getMessage());
        return Message.exception(Code.C415);
    }

    @ExceptionHandler({NotAcceptableStatusException.class, HttpMediaTypeNotAcceptableException.class})
    @ResponseStatus(HttpStatus.OK)
    public Message handleNotAcceptableException(Exception e) {
        log.error(e.getMessage());
        return Message.exception(Code.C406);
    }

    @ExceptionHandler(value = UnauthorizedException.class)
    @ResponseStatus(HttpStatus.OK)
    public Message handleUnauthorizedException(Exception e) {
        log.error("权限不足，{}", e.getMessage());
        return Message.exception(Code.C403, "暂无访问权限");
    }

    @ExceptionHandler(value = FeignException.class)
    @ResponseStatus(HttpStatus.OK)
    public Message handleFeignException(Exception e) {
        String message = e.getMessage();
        log.error("插件请求失败: {}", e.getMessage(), e);
        if (e instanceof RetryableException && e.getCause() instanceof ConnectException){
            message = "服务可能已关闭，请联系管理员";
        } else if (e instanceof FeignException){
            if (((FeignException) e).status() == HttpStatus.NOT_ACCEPTABLE.value()){
                message = "当前IP不在允许访问范围内";
            }
        }
        return Message.exception(Code.C400, message);
    }
}
